package com.cgy.utils.netx.ftp.utils;

import com.cgy.utils.netx.ftp.constant.FileInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author CHTK
 */
@Slf4j
public class Ftps {

    private FTPClient ftpClient;

    private Ftps() {}

    private Ftps(FTPClient ftpClient) {
        this.ftpClient = ftpClient;
    }

    /**
     * 获取FTPClient对象
     *
     * @param ftpHost     FTP主机服务器
     * @param ftpPassword FTP 登录密码
     * @param ftpUserName FTP登录用户名
     * @param ftpPort     FTP端口 默认为21
     * @return
     */
    public static Ftps getFTPClient(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort) {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = new FTPClient();
            ftpClient.connect(ftpHost, ftpPort);
            ftpClient.login(ftpUserName, ftpPassword);
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                System.out.println("未连接到FTP，用户名或密码错误。");
                ftpClient.disconnect();
            } else {
                System.out.println("FTP连接成功。");
            }
        } catch (SocketException e) {
            e.printStackTrace();
            System.out.println("FTP的IP地址可能错误，请正确配置。");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("FTP的端口错误,请正确配置。");
        }
        return new Ftps(ftpClient);
    }

    /**
     * 切换目录
     * @param path
     */
    public void changeDirectory(String path) {
        ftpClient.setControlEncoding("UTF-8");
        try {
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param path
     * @return
     * @throws IOException
     */
    public List<FileInfo> listPathFile(final String path) throws IOException {
        FTPFile[] ftpFiles = ftpClient.listFiles(path);
        return FtpFile.listPathFiles(ftpFiles);
    }
    /**
     *
     * @throws IOException
     * @return
     */
    public List<FileInfo> listFile() throws IOException {
        if(null != ftpClient) {
            FTPFile[] ftpFiles = ftpClient.listFiles();
            return FtpFile.listPathFiles(ftpFiles);
        }
        return null;
    }
    /**
     * 删除文件
     * @param path
     * @param fileName
     */
    public void deleteFile(String path, String fileName) {
        changeDirectory(path);
        try {
            ftpClient.deleteFile(fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 删除文件
     * @param path
     * @param fileName
     */
    public void appendFile(String path, String fileName, InputStream inputStream) {
        changeDirectory(path);
        try {
            ftpClient.storeFile(fileName, inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 重命名
     * @param oldName
     * @param newName
     * @return
     */
    public boolean rename(final String path, final String oldName, final String newName) {
        changeDirectory(path);
        try {
            return ftpClient.rename(oldName, newName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
    /**
     * 从FTP服务器下载文件
     *
     * @param ftpPath FTP服务器中文件所在路径 格式： ftptest/aa
     * @param localPath 下载到本地的位置 格式：H:/download
     * @param fileName 文件名称
     */
    public boolean downloadFtpFile(String ftpPath, String localPath, String fileName) {

        changeDirectory(ftpPath);
        try {
            File localFile = new File(localPath + File.separatorChar + fileName);
            OutputStream os = new FileOutputStream(localFile);
            ftpClient.retrieveFile(fileName, os);
            os.close();
        } catch (FileNotFoundException e) {
            log.info("没有找到" + ftpPath + "文件");
            e.printStackTrace();
            return false;
        } catch (SocketException e) {
            log.info("连接FTP失败.");
            e.printStackTrace();
            return false;
        } catch (Exception e) {
            log.info("文件读取错误。");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Description: 向FTP服务器上传文件
     *
     * @param ftpPath     FTP服务器中文件所在路径 格式： ftptest/aa
     * @param fileName    ftp文件名称
     * @param input       文件流
     * @return 成功返回true，否则返回false
     */
    public boolean uploadFile(String ftpPath, String fileName, InputStream input) {
        boolean success = false;
        try {
            int reply;
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                return success;
            }
            changeDirectory(ftpPath);

            ftpClient.storeFile(fileName, input);

            input.close();
            success = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 方法描述：检验指定路径的文件是否存在ftp服务器中
     *
     * @param filePath 指定绝对路径的文件/TEST/20161010
     * @return 存在返回true，不存在返回false
     */
    public boolean isFTPFileExist(String fileName, String filePath) {

        try {
            changeDirectory(filePath);
            // 检验文件是否存在
            InputStream is = ftpClient.retrieveFileStream(new String(fileName.getBytes("GBK"), FTP.DEFAULT_CONTROL_ENCODING));
            if (is == null || ftpClient.getReplyCode() == FTPReply.FILE_UNAVAILABLE) {
                log.info("文件" + filePath + "/" + fileName + "不存在");
                return false;
            }
            log.info("文件" + filePath + "/" + fileName + "存在");
            if (is != null) {
                is.close();
                ftpClient.completePendingCommand();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     *
     * @throws IOException
     */
    public void release() throws IOException {
        if(null != ftpClient) {
            ftpClient.logout();
            ftpClient.disconnect();
        }
    }

    /**
     *
     */
    public static class FtpFile {
        /**
         *
         * @param ftpFiles
         * @return
         */
        public static List<FileInfo> listPathFiles(FTPFile[] ftpFiles) {
            List<FileInfo> stringList = new ArrayList<>();
            if(null != ftpFiles) {
                for (FTPFile ftpFile : ftpFiles) {
                    FileInfo fileInfo = new FileInfo();
                    fileInfo.setName(ftpFile.getName());
                    fileInfo.setSize(ftpFile.getSize());
                    fileInfo.setTimestamp(ftpFile.getTimestamp());
                    fileInfo.setType(ftpFile.getType());
                    fileInfo.setGroup(ftpFile.getGroup());
                    fileInfo.setDirectory(ftpFile.isDirectory());
                    fileInfo.setFile(ftpFile.isFile());
                    fileInfo.setLink(ftpFile.getLink());
                    stringList.add(fileInfo);
                }
            }
            return stringList;

        }
    }
}
